﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
using WPFExcelReport;
using WPFExcelReport.Helpers;
using System.Data;
using ModbusLib;
using System.Linq;
namespace WPFExcelReport
{

    /// <summary>
    /// 与客户端的 连接通信类(包含了一个 与客户端 通信的 套接字，和线程)
    /// </summary>
    public partial class ZLANClient
    {
        public void Send(string devtyp, string command, object SlaveId, object StartAddress, object DataLength, object DataSend)
        {
            Helper.GetTime(ref date, ref time);
            //Helpers.LogHelper.info(time + ":" + this.PLCIP + " SND :" + SlaveId.ToString());
            byte[] bytes = null;
            string[] sWriteData = null;
            switch (devtyp)
            {
                case "FXPLC":
                    switch (command)
                    {
                        case "0":
                            bytes = (byte[])PLCFX.PlcRead(int.Parse((string)StartAddress), int.Parse((string)DataLength), DataSend);
                            break;
                        case "1":
                            sWriteData = ((string)DataSend).Split(',');
                            bytes = (byte[])PLCFX.PlcWrite(int.Parse((string)StartAddress), int.Parse((string)DataLength), sWriteData);
                            break;
                    }
                    break;
                case "S7200":
                    bytes = (byte[])PLCS7.PlcWrite(command, StartAddress, DataLength, DataSend);
                    break;

                case "AM3011":
                    //string command, object SlaveId,object StartAddress, object DataLength, object DataSend
                    bytes = (byte[])PLCDM3011.PlcWrite(command, SlaveId, StartAddress, DataLength, DataSend);
                    break;
                case "XM05B3":
                case "YHA12":
                    bytes = (byte[])PYH.PlcWrite(command, SlaveId, StartAddress, DataLength, DataSend);
                    break;
                case "XK31":
                case "HT1300":
                    bytes = (byte[])PYH.PlcWrite(command, SlaveId, StartAddress, DataLength, DataSend);
                    break;
                case "CC5D99RS":
                    //string command, object SlaveId,object StartAddress, object DataLength, object DataSend
                    bytes = (byte[])CC5D99RS.PlcWrite(command, SlaveId, StartAddress, DataLength, DataSend);
                    break;
            }
            if (bytes == null)
                return;
            SendMessage(bytes);
        }
        int IOFAILS = 0;
        long ticks = -1;
        public void ReceiveMessage()
        {

            while (true)
            {
                try
                {
                    _bytesRead = SocketClient.Receive(received);
                    if (_bytesRead == 0)
                        continue;
                    if (!SocketClient.Connected)
                        continue;
                    if (CQ.devtyp == null)
                        continue;
                    if (_bytesRead > 0)
                    {
                        Helper.GetTime(ref date, ref time, ref ticks);
                        switch (CQ.devtyp)
                        {
                            case "FXPLC":
                                ProcessData(GetFXMsg);
                                break;
                            case "S7200":
                                ProcessData(GetS7Msg);
                                break;
                            case "AM3011":
                                ProcessData(GetAM3011Msg);
                                break;
                            case "YHA12":
                                ProcessData(GetYHMsg);
                                break;
                            case "HT1300":
                                ProcessData(GetHTMsg);
                                break;
                            case "CC5D99RS":
                                ProcessData(GetCDMsg);
                                break;
                            case "XM05B3":
                                ProcessData(GetXM05B3Msg);
                                break;
                            case "XK31":
                                ProcessData(GetXK31Msg);
                                break;
                        }
                    }
                    else  //当等于0的时候，竟然是SOCKET结束了？
                    {
                        // All the data has arrived; put it in response.
                        ProcessData(null);
                        CloseConnection();
                    }
                    //LogHelper.info(time + ":" + PLCIP + " GET:" + CQ.SlaveID);
                }
                catch (SocketException ex)
                {
                    //LogHelper.error(ex.StackTrace + ex.Message);
                    //CloseConnection();
                }
                catch (IOException ex)
                {
                    IOFAILS++;
                    if (IOFAILS > 100 * 10)
                    {
                        IOFAILS = 0;
                        //CloseConnection();
                    }
                    //LogHelper.error(time + ":"+PLCIP+":" + IOFAILS+ "Read fail:");
                    // All the data has arrived; put it in response.
                    // ProcessData(recvDataAction);
                }
                finally
                {
                    IsMessageHandling = false;
                }
            }
        }

        public void GetFXMsg(string name, byte[] data, int length)
        {

        }
        public void GetYHMsg(string name, byte[] data, int length)
        {

            string vint = "0";
            //将接收到的消息数组里真实消息转成字符串  
            if (length == 0)
                return;
            string strMsg = "";
            string value = "0";
            int idx = -1;
            strMsg = Encoding.ASCII.GetString(data, 0, length);
            string[] values = strMsg.Split(new char[] { '+' });
            foreach (string v in values)
            {
                if (v == "")
                    continue;
                if (vint == v)
                    continue;
                vint = v;
                idx = v.IndexOf("g");

                if (idx > 0)
                {
                    value = v.Substring(0, idx);
                }
                else
                {
                    idx = v.IndexOf("kg");
                    if (idx > 0)
                    {
                        value = v.Substring(0, idx);
                    }
                }
                if (idx < 0)
                    continue;
                VZL.PM["BDEKEY"] = CQ.MSETID;
                VZL.PM["BDEKEN"] = CQ.BDEKEN;
                VZL.PM["AMVVAL"] = value;
                VZL.PM["CHANNEL"] = CQ.Channel;
                VZL.PM["DATE"] = date;
                VZL.PM["TIME"] = time;
                VZL.PM["TICKS"] = ticks;
                VZL.VAMV.NAMVALUE(VZL.PM);
                Thread.Sleep(300);
                IsPortReaday = true;
            }
        }
        public void GetXK31Msg(string name, byte[] data, int length)
        {
            string vint = "0";
            byte[] body = new byte[3];
            int c = 0;
            //将接收到的消息数组里真实消息转成字符串  
            if (length == 0)
                return;
            if (length < 6)
                return;
            int lg = 3;
            body = new byte[lg];
            c = 2;
            for (int i = 1; i < 1 + lg; i++)
            {
                body[c] = data[i];
                c--;
            }
            int Channel = int.Parse((string)CQ.Channel);
            int b0 = body[0];
            int b1= body[1];
            int b2 = body[2];
            int bx1 =(b0 / 16) * 10 + b0 - (b0 / 16) * 16;
            int bx2 = (b1 / 16) * 10 + b1 - (b1 / 16) * 16;
            int bx3 = (b2 / 16) * 10 + b2 - (b2 / 16) * 16;
            vint = (bx1 * 100 + bx2 + bx3 * 0.01).ToString();
            VZL.PM["BDEKEY"] = CQ.MSETID;
            VZL.PM["BDEKEN"] = CQ.BDEKEN;
            VZL.PM["AMVVAL"] = vint;
            VZL.PM["CHANNEL"] = CQ.Channel;
            VZL.PM["DATE"] = date;
            VZL.PM["TIME"] = time;
            VZL.PM["TICKS"] = ticks;
            VZL.VAMV.NAMVALUE(VZL.PM);
            IsPortReaday = true;

        }
        public void GetHTMsg(string name, byte[] data, int length)
        {

            string vint = "0";
            //将接收到的消息数组里真实消息转成字符串  
            //wn00000.00kg
            if (length == 0)
                return;
            string strMsg = "";
            string value = "0";
            int idx = -1;
            strMsg = Encoding.ASCII.GetString(data, 0, length);
            string[] values = strMsg.Split(new char[] { 'w', 'n' });
            foreach (string v in values)
            {
                if (v == "")
                    continue;
                if (vint == v)
                    continue;
                vint = v;
                idx = v.IndexOf("kg");
                if (idx > 0)
                {
                    value = v.Substring(0, idx);
                }
                else
                {
                    idx = v.IndexOf("g");
                    if (idx > 0)
                    {
                        value = v.Substring(0, idx);
                    }
                }
                if (idx < 3)
                    continue;
                if (value.Contains("-"))
                    continue;
                VZL.PM["BDEKEY"] = CQ.MSETID;
                VZL.PM["BDEKEN"] = CQ.BDEKEN;
                VZL.PM["AMVVAL"] = value;
                VZL.PM["CHANNEL"] = CQ.Channel;
                VZL.PM["DATE"] = date;
                VZL.PM["TIME"] = time;
                VZL.PM["TICKS"] = ticks;
                VZL.VAMV.NAMVALUE(VZL.PM);
                Thread.Sleep(300);
                IsPortReaday = true;
            }
        }
        public void GetCDMsg(string name, byte[] data, int length)
        {
            string vint = "0";
            byte[] body = new byte[3];
            int c = 0;
            //将接收到的消息数组里真实消息转成字符串  
            if (length == 0)
                return;
            string strMsg = "";
            strMsg = Encoding.ASCII.GetString(data, 0, length);
            string[] values = strMsg.Split(new char[] { 'M', 'Y' });
            foreach (string v in values)
            {
                if (v == "")
                    continue;
                if (vint == v)
                    continue;
                vint = v;
                VZL.PM["BDEKEY"] = CQ.MSETID;
                VZL.PM["BDEKEN"] = CQ.BDEKEN;
                VZL.PM["AMVVAL"] = vint;
                VZL.PM["CHANNEL"] = CQ.Channel;
                VZL.PM["DATE"] = date;
                VZL.PM["TIME"] = time;
                VZL.PM["TICKS"] = ticks;
                VZL.VAMV.NAMVALUE(VZL.PM);
                Thread.Sleep(300);
                IsPortReaday = true;
            }
        }
        public void GetS7Msg(string name, byte[] data, int length)
        {

            //将接收到的消息数组里真实消息转成字符串  
            if (length > 0)
            {

                //如果接收到的数据长度为1，值为E5H (229)，则为确认码，返回读写确认命令
                if (data[0] == (byte)229 && length == 1)
                {
                    //收到数据
                    byte[] dataSend = new byte[6];
                    dataSend[0] = 16;
                    //站号
                    dataSend[1] = 0x02;
                    dataSend[2] = 0x00;
                    dataSend[3] = 0x5C;
                    dataSend[4] = (byte)(dataSend[3] + dataSend[1]);
                    dataSend[5] = 0x16;
                    //Thread.Sleep(300);
                    SendMessage(dataSend);
                }
                else
                {
                    if (data[0] == (byte)229)
                    {
                        IsPortReaday = false;
                    }
                    else
                    {
                        string vint = "0";
                        byte[] b = new byte[3];
                        int c = 0;

                        switch (data[24])
                        {
                            case (byte)1:
                                vint = System.Convert.ToInt32(data[25]).ToString();
                                break;
                            case (byte)8:
                                vint = System.Convert.ToInt32(data[25]).ToString();
                                break;
                            case (byte)10:
                                b = new byte[2];
                                for (int i = 25; i < 26; i++)
                                {
                                    b[c] = data[i];
                                    c++;
                                }
                                vint = System.BitConverter.ToInt32(b, 0).ToString();
                                break;
                            case (byte)20:
                                b = new byte[3];
                                for (int i = 25; i < 28; i++)
                                {
                                    b[c] = data[i];
                                    c++;
                                }
                                vint = System.BitConverter.ToInt32(b, 0).ToString();
                                break;
                        }
                        VZL.PM["BDEKEY"] = CQ.MSETID;
                        VZL.PM["BDEKEN"] = CQ.BDEKEN;
                        VZL.PM["AMVVAL"] = vint;
                        VZL.PM["DATE"] = date;
                        VZL.PM["TIME"] = time;
                        VZL.PM["TICKS"] = ticks;
                        VZL.VAMV.NAMVALUE(VZL.PM);
                        IsPortReaday = true;
                    }
                }
            }
        }

        public void GetAM3011Msg(string name, byte[] data, int length)
        {
            string vint = "0";
            byte[] body = new byte[3];
            int c = 0;
            //将接收到的消息数组里真实消息转成字符串  
            if (length == 0)
                return;
            byte function = data[1];
            int lg = 1;
            switch (function)
            {
                case (byte)01://读取输出寄存器状态   
                    IsPortReaday = true;
                    break;
                case (byte)02://读取输入开关量状态
                    IsPortReaday = true;
                    break;
                case (byte)03://读保持寄存器
                    IsPortReaday = true;
                    break;
                case (byte)04://读输入寄存器
                              //前2组地位，后2组高位
                    lg = Convert.ToInt32(data[2].ToString("X2"), 16);
                    body = new byte[lg];
                    c = 0;
                    for (int i = 3; i < 3 + lg; i++)
                    {
                        body[c] = data[i];

                        c++;
                    }
                    int Channel = int.Parse((string)CQ.Channel);

                    var count = lg / 2;
                    ushort[] Data = new ushort[count];
                    ByteArrayReader breader = new ByteArrayReader(body);
                    for (int i = 0; i < count; i++)
                        Data[i] = breader.ReadUInt16BE();
                    count = lg / 4;
                    int[] Data32 = new int[count];
                    for (int i = 0; i < count; i++)
                        Data32[i] = Data[i * 2 + 1] * 65536 + Data[i * 2];
                    vint = Data32[Channel - 1].ToString();
                    VZL.PM["BDEKEY"] = CQ.MSETID;
                    VZL.PM["BDEKEN"] = CQ.BDEKEN;
                    VZL.PM["AMVVAL"] = vint;
                    VZL.PM["CHANNEL"] = CQ.Channel;
                    VZL.PM["DATE"] = date;
                    VZL.PM["TIME"] = time;
                    VZL.PM["TICKS"] = ticks;
                    VZL.VAMV.NAMVALUE(VZL.PM);
                    IsPortReaday = true;
                    break;
                case (byte)05://设置单个继电器
                    IsPortReaday = true;
                    break;
                case (byte)06://设置单个保持寄存器
                    IsPortReaday = true;
                    break;
                case (byte)0F://设置多个继电器
                    IsPortReaday = true;
                    break;
                case (byte)16://设置多个保持寄存器
                    IsPortReaday = true;
                    break;
            }
        }
        public void GetXM05B3Msg(string name, byte[] data, int length)
        {
            string vint = "0";
            byte[] body = new byte[3];
            int c = 0;
            //将接收到的消息数组里真实消息转成字符串  
            if (length == 0)
                return;
            if (length <12)
                return;
            int lg = 3;
            body = new byte[lg];
            c = 0;
            for (int i = 5; i < 5 + lg; i++)
            {
                body[c] = data[i];
                c++;
            }
            int Channel = int.Parse((string)CQ.Channel); 
            vint = ((body[0] * 16 * 16 * 16 * 16 + body[1] * 16 * 16 + body[2]) * 0.01).ToString();
            VZL.PM["BDEKEY"] = CQ.MSETID;
            VZL.PM["BDEKEN"] = CQ.BDEKEN;
            VZL.PM["AMVVAL"] = vint;
            VZL.PM["CHANNEL"] = CQ.Channel;
            VZL.PM["DATE"] = date;
            VZL.PM["TIME"] = time;
            VZL.PM["TICKS"] = ticks;
            VZL.VAMV.NAMVALUE(VZL.PM);
            IsPortReaday = true;

        }
    }
}
